package com.cgc.venus.server.app.service;

import com.cgc.venus.server.app.bean.ImageParaBean;
import com.cgc.venus.server.app.bean.ImageVersionDetailBean;
import com.cgc.venus.server.app.bean.RepoBean;
import com.cgc.venus.server.app.bean.RepoDetialBean;
import com.cgc.venus.server.app.inter.AppRepositoryService;
import com.cgc.venus.server.core.base.AbstractBaseService;
import com.cgc.venus.server.core.bean.response.VenusResponseStatus;
import com.cgc.venus.server.core.exception.VenusException;
import com.cgc.venus.server.core.harbor.HarborService;
import com.cgc.venus.server.core.harbor.model.Tag;
import com.cgc.venus.server.core.utils.DateUtil;
import com.cgc.venus.server.core.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by xiaobin on 2017/9/25.
 */
@Service
@ConfigurationProperties(prefix = "app")
public class AppRepositoryServiceImpl extends AbstractBaseService implements AppRepositoryService {
    @Autowired
    private JdbcTemplate jdbcTemplateImpl;
    @Autowired
    private HarborService harborServiceImpl;
    private String repositoryUrl;

    public String getRepositoryUrl() {
        return repositoryUrl;
    }

    public void setRepositoryUrl(String repositoryUrl) {
        this.repositoryUrl = repositoryUrl;
    }

    //根据关键字和空间名称查私有空间信息
    @Override
    public List<RepoBean> repoPrivateQuery(String queryKey, String spaceName) throws VenusException {
        if (queryKey == null) {
            queryKey = "";
        }
        String sql = "select repo.name as 'repoName',repo.pull_count as 'pullCount',\n" +
                "case when repo.name in (select name from t_repository_public) \n" +
                "then  '公有' \n" +
                "else  '私有'\n" +
                "END as repoType\n" +
                "From repository repo,t_namespace ns \n" +
                "where SUBSTRING_INDEX(repo.name,'/',1)=ns.harbor_project_name\n" +
                "and ns.harbor_project_name=? \n" +
                "and repo.name like ?";
        List<Object> objects = new ArrayList<Object>();
        objects.add(spaceName);
        objects.add("%" + queryKey + "%");

        List<RepoBean> repoBeanListTmp = jdbcTemplateImpl.query(sql, new RowMapper<RepoBean>() {
            public RepoBean mapRow(ResultSet rs, int i) throws SQLException {
                RepoBean repoBean = new RepoBean();
                repoBean.setRepoName(rs.getString("repoName"));
                repoBean.setPullCount(rs.getInt("pullCount"));
                repoBean.setRepoType(rs.getString("repoType"));

                return repoBean;
            }
        }, objects.toArray());
        return repoBeanListTmp;
    }

    //根据关键字和空间名称查公有空间信息
    @Override
    public List<RepoBean> repoPublicQuery(String queryKey, String spaceName) throws VenusException {
        if (queryKey == null) {
            queryKey = "";
        }

//        String sql="select name as 'repoName',pull_count as 'pullCount' From repository where name like ? ";
        String sql = "select repo.name as repoName,repo.pull_count as pullCount \n" +
                "From t_namespace ns ,repository repo\n" +
                "where SUBSTRING_INDEX(repo.name,'/',1)=ns.harbor_project_name\n" +
                "and repo.name in (select name From t_repository_public)\n" +
                "and ns.harbor_project_name=?\n" +
                "and repo.name like ?";
        List<Object> objects = new ArrayList<Object>();
        objects.add(spaceName);
        objects.add("%" + queryKey + "%");

        List<RepoBean> repoBeanListTmp = jdbcTemplateImpl.query(sql, new RowMapper<RepoBean>() {
            public RepoBean mapRow(ResultSet rs, int i) throws SQLException {
                RepoBean repoBean = new RepoBean();
                repoBean.setRepoName(rs.getString("repoName"));
                repoBean.setPullCount(rs.getInt("pullCount"));
                return repoBean;
            }
        }, objects.toArray());
        return repoBeanListTmp;
    }

    @Override
    //    根据镜像查询私有空间下的镜像
    public List<RepoDetialBean> imageQuery(String repoName) throws VenusException {
        List<RepoDetialBean> repoDetialBeanList = new ArrayList<RepoDetialBean>();
        List<Tag> tagList = harborServiceImpl.getRepositorieTags(repositoryUrl, repoName);
        for (Tag tag : tagList) {
            RepoDetialBean repoDetialBean = new RepoDetialBean();
            repoDetialBean.setImageLabel(tag.getName());
            repoDetialBean.setCommand(tag.getPullCmd());
            repoDetialBean.setCreateTime(tag.getCreated().toString());
            repoDetialBean.setEditor(tag.getAuthor());
            repoDetialBeanList.add(repoDetialBean);
        }
        return repoDetialBeanList;
    }

    //    根据镜像名称删除镜像
    @Override
    public boolean repoDelete(String nameRepo, String tags) throws VenusException {
        if (StringUtil.isEmpty(nameRepo)) {
            throw new VenusException(VenusResponseStatus.NO_CONTENT, "镜像名称为空异常");
        }
        boolean flag = false;
        if (StringUtil.isEmpty(tags)) {
            // 删除整个镜像
            flag = harborServiceImpl.repositoryDelete(nameRepo);
            if (flag) {
                // 同时删除镜像的版本描述
                deleteImageVersionDescribed(nameRepo);
            }
        } else {
            flag = harborServiceImpl.repositoryDelete(nameRepo, tags);
            if (flag) {
                // 同时删除镜像的版本描述
                deleteImageVersionDescribed(nameRepo,tags);
            }
        }
        return flag;
    }

    //    根据镜像名称查询是该镜像是否在私有空间表存在
    public boolean repoNameExist(String repoName) throws VenusException {
        String sql = "select *from t_repository_public where name=?";
        List<Object> objects = new ArrayList<Object>();
        objects.add(repoName);
        List<Map<String, Object>> mapList = jdbcTemplateImpl.queryForList(sql, objects.toArray());
        if (mapList == null || mapList.size() == 0) {
            return false;
        }
        return true;
    }

    //    设置镜像为公有
    @Override
    public boolean repoSetPublic(String nameRepo) throws VenusException {

        String sql = "insert into t_repository_public(id,name,create_time,last_update_time) values(?,?,NOW(),NOW())";
//        String sql2="select "
        List<Object> objects = new ArrayList<Object>();
        String id = StringUtil.getUUID();
        objects.add(id);
        objects.add(nameRepo);
        int i = jdbcTemplateImpl.update(sql, objects.toArray());
        if (i == 0) {
            throw new VenusException(VenusResponseStatus.MYSQL_DB_EXCEPTION, "数据库新增异常");
        }
        return true;

    }

    //    设置镜像为私有
    @Override
    public boolean repoSetPrivate(String nameRepo) throws VenusException {
        String sql = "delete from t_repository_public where name=?";
        List<Object> objects = new ArrayList<Object>();
        objects.add(nameRepo);
        int i = jdbcTemplateImpl.update(sql, objects.toArray());
        if (i != 1) {
            return false;
        }
        return true;
    }

    @Override
    public List<Tag> appTagsQuery(String name) throws VenusException {
        return harborServiceImpl.getRepositorieTags(repositoryUrl, name);
    }

    /*
    * 获得镜像版面说明
    * */
    @Override
    public ImageVersionDetailBean getImageVersionDescribed(String image, String version) throws VenusException {
        String sql = "SELECT id,image,version,user,described FROM t_image_version_detail WHERE image=? AND version=? ";
        List<Object> list = new ArrayList<>();
        list.add(image);
        list.add(version);
        ImageVersionDetailBean imageVersionDetailBean = new ImageVersionDetailBean();

        try {
            Map<String, Object> map = jdbcTemplateImpl.queryForMap(sql, list.toArray());
            if (map.size() > 0) {
                imageVersionDetailBean.setId((String) map.get("id"));
                imageVersionDetailBean.setImage((String) map.get("image"));
                imageVersionDetailBean.setVersion((String) map.get("version"));
                imageVersionDetailBean.setDescribed((String) map.get("described"));
            }
        } catch (EmptyResultDataAccessException e) {
            return imageVersionDetailBean;
        }
        return imageVersionDetailBean;
    }

    @Override
    public int addImageVersionDescribed(ImageVersionDetailBean imageVersionDetailBean) throws VenusException {
        String sql = "INSERT INTO t_image_version_detail(id,image,version,described,user,create_time,last_update_time) " +
                "VALUES(?,?,?,?,?,NOW(),NOW())";
        List<Object> list = new ArrayList<>();
        list.add(StringUtil.getUUID());
        list.add(imageVersionDetailBean.getImage());
        list.add(imageVersionDetailBean.getVersion());
        list.add(imageVersionDetailBean.getDescribed());
        list.add(imageVersionDetailBean.getUser());
        int row = jdbcTemplateImpl.update(sql, list.toArray());
        return row;
    }

    @Override
    public int editImageVersionDescribed(ImageVersionDetailBean imageVersionDetailBean) throws VenusException {
        String sql = "UPDATE t_image_version_detail SET described=?, user=?, last_update_time=NOW() WHERE id = ?";
        List<Object> list = new ArrayList<>();
        list.add(imageVersionDetailBean.getDescribed());
        list.add(imageVersionDetailBean.getUser());
        list.add(imageVersionDetailBean.getId());
        int row = jdbcTemplateImpl.update(sql, list.toArray());
        return row;
    }

    /*
    * 获得所有镜像版本的明细说明
    * */
    @Override
    public List<ImageVersionDetailBean> getImageDescribed(String image) throws VenusException {
        String sql = "SELECT ti.id,ti.image,ti.version,tu.name,ti.described,ti.last_update_time FROM t_image_version_detail ti " +
                "LEFT JOIN t_user tu ON tu.id=ti.user WHERE ti.image= ? ";
        List<Object> list = new ArrayList<>();
        list.add(image);
        List<ImageVersionDetailBean> imageVersionDetailBeanList = new ArrayList<ImageVersionDetailBean>();
        try {
            imageVersionDetailBeanList = jdbcTemplateImpl.query(sql, new RowMapper<ImageVersionDetailBean>() {
                @Override
                public ImageVersionDetailBean mapRow(ResultSet rs, int i) throws SQLException {
                    ImageVersionDetailBean imageVersionDetailBean = new ImageVersionDetailBean();
                    imageVersionDetailBean.setId(rs.getString("id"));
                    imageVersionDetailBean.setImage(rs.getString("image"));
                    imageVersionDetailBean.setVersion(rs.getString("version"));
                    imageVersionDetailBean.setUser(rs.getString("name"));
                    imageVersionDetailBean.setDescribed(rs.getString("described"));
                    Timestamp timestamp = rs.getTimestamp("last_update_time");
                    String lastUpdateTime = DateUtil.TimeStamp2Date(timestamp, DateUtil.yyyy_MM_dd_HH_mm_ss);
                    imageVersionDetailBean.setLastUpdateTime(lastUpdateTime);
                    return imageVersionDetailBean;
                }
            }, list.toArray());
        } catch (EmptyResultDataAccessException e) {
            return imageVersionDetailBeanList;
        }
        return imageVersionDetailBeanList;
    }

    @Override
    public int deleteImageVersionDescribed(String image) throws VenusException {
        String sql = "DELETE FROM t_image_version_detail WHERE image = ?" ;
        List<Object> list = new ArrayList<>();
        list.add(image);
        int row = jdbcTemplateImpl.update(sql,list.toArray());
        return row;
    }

    @Override
    public int deleteImageVersionDescribed(String image, String version) throws VenusException {
        String sql = "DELETE FROM t_image_version_detail WHERE image = ? AND version=? " ;
        List<Object> list = new ArrayList<>();
        list.add(image);
        list.add(version);
        int row = jdbcTemplateImpl.update(sql,list.toArray());
        return row;
    }

    @Override
    public List<ImageParaBean> getImageParaByNamespace(String namespace) throws VenusException {
        String sql="SELECT rep.`name`, ib.described AS `desc`, ib.app_kind AS deployType, ib.requests_memory AS memoryRequest, ib.limits_memory AS memoryMax, ib.requests_cpu AS cpuRequest, ib.limits_cpu AS cpuMax, ib.replicas AS instanceCount, ib.image_pull_policy AS getImagesType, ib.command, arg.commandPara, env.env FROM t_namespace ns LEFT JOIN project p ON p.`name` = ns.harbor_project_name LEFT JOIN repository rep ON rep.project_id = p.project_id LEFT JOIN t_image_base ib ON ib.image = rep.`name` LEFT JOIN ( SELECT image, group_concat(arg ORDER BY serial_number) AS commandPara FROM t_image_command_agrs GROUP BY image ) arg ON arg.image = rep.`name` LEFT JOIN ( SELECT image, group_concat( CONCAT_WS(':', env_key, env_value)) AS env FROM t_image_env GROUP BY image ) env ON env.image = rep.`name` WHERE ns.kube_name = ?";
        List<Object> para = new ArrayList<>();
        para.add(namespace);
        List<ImageParaBean> imageParaBeans=jdbcTemplateImpl.query(sql, para.toArray(), new BeanPropertyRowMapper<ImageParaBean>(ImageParaBean.class));
        return imageParaBeans;
    }

    @Transactional
    @Override
    public String setImagePara(List<ImageParaBean> imageParaBeans,String namespace) throws VenusException {
        if(imageParaBeans==null||imageParaBeans.size()==0){
            return "参数设置失败,待设置的镜像为空!";
        }
        List<String> deleteSqls=new ArrayList<>();
        List<String> insertSqls=new ArrayList<>();
        String deleteBaseImage = "";
        String deleteImageArgs = "";
        String deleteImageEnv = "";

        String insertBaseImage = "";
        String insertImageArgs = "";
        String insertImageEnv = "";
        for(ImageParaBean ipb:imageParaBeans){
            String image=ipb.getName();
            if(StringUtil.isEmpty(image)){
                return "参数设置失败,镜像名称不能为空!";
            }
            //验证镜像是否是本空间的镜像
            String valideSql="SELECT * FROM t_namespace ns INNER JOIN project p ON p.`name` = " +
                    "ns.harbor_project_name INNER JOIN repository rep " +
                    "ON rep.project_id = p.project_id " +
                    "WHERE ns.kube_name = ? AND rep.`name` = ?";
            List<Object> list=new ArrayList<>();
            list.add(namespace);
            list.add(image);
            List<Map<String, Object>> vr=this.jdbcTemplateImpl.queryForList(valideSql,list.toArray());
            if(vr==null||vr.size()==0){
                return "参数设置失败,镜像:"+image+"不属于当前空间的镜像,无权限修改该镜像!";
            }

            deleteBaseImage = "delete from t_image_base  where image='"+image+"' ";
            deleteImageArgs = "delete from t_image_command_agrs  where image='"+image+"' ";
            deleteImageEnv  = "delete from t_image_env  where image='"+image+"' ";
            deleteSqls.add(deleteBaseImage);
            deleteSqls.add(deleteImageArgs);
            deleteSqls.add(deleteImageEnv);
            String desc="";
            if(!StringUtil.isEmpty(ipb.getDesc())){
                desc=ipb.getDesc();
            }

            String deployType="Deployment";
            if(!StringUtil.isEmpty(ipb.getDeployType())){
                deployType=ipb.getDeployType();
            }
            String reqM="100Mi";
            if(!StringUtil.isEmpty(ipb.getMemoryRequest())){
                reqM=ipb.getMemoryRequest();
            }
            String reqCpu="100m";
            if(!StringUtil.isEmpty(ipb.getCpuRequest())){
                reqCpu=ipb.getCpuRequest();
            }
            String limitM="1Gi";
            if(!StringUtil.isEmpty(ipb.getMemoryMax())){
                limitM=ipb.getMemoryMax();
            }
            String limitCpu="1";
            if(!StringUtil.isEmpty(ipb.getCpuMax())){
                limitCpu=ipb.getCpuMax();
            }

            int replicas=1;
            try {
                if(!StringUtil.isEmpty(ipb.getInstanceCount())){
                    replicas=Integer.parseInt(ipb.getInstanceCount());
                }
            }catch (Exception ex){
                ex.printStackTrace();
                return "参数设置失败,启动实例个数格式异常!";
            }
            int start_command=1;
            String command="";
            if(!StringUtil.isEmpty(ipb.getCommand())){
                start_command=2;
                command=ipb.getCommand();
            }
            String image_pull_policy="Always";
            if(!StringUtil.isEmpty(ipb.getGetImagesType())){
                image_pull_policy=ipb.getGetImagesType();
            }

            insertBaseImage="INSERT INTO t_image_base" +
                    "(id,image,described,app_kind," +
                    "requests_memory,requests_cpu," +
                    "limits_memory,limits_cpu," +
                    "replicas,start_command," +
                    "command,image_pull_policy," +
                    "create_time,last_update_time) " +
                    "VALUES ('"+StringUtil.getUUID()+"','"+image+"','"+desc+"','"+deployType+"','"+reqM+"','"+reqCpu+"','"+limitM+"','"+limitCpu+"',"+replicas+","+start_command+",'"+command+"','"+image_pull_policy+"',NOW(),NOW())";
            insertSqls.add(insertBaseImage);
            if(!StringUtil.isEmpty(ipb.getCommandPara())){
                try {
                    String[] args=ipb.getCommandPara().split(",");
                    int index=0;
                    for(String arg:args){
                        insertImageArgs="INSERT INTO t_image_command_agrs(id,image,serial_number,arg,create_time,last_update_time) " +
                                "VALUES ('"+StringUtil.getUUID()+"','"+image+"',"+index+",'"+arg+"',NOW(),NOW())";
                        insertSqls.add(insertImageArgs);
                        index++;
                    }
                }catch (Exception ex){
                    ex.printStackTrace();
                    return "参数设置失败,启动命令参数格式异常!";
                }
            }
            if(!StringUtil.isEmpty(ipb.getEnv())){
                try {
                    String[] envs=ipb.getEnv().split(",");
                    for(String env:envs){
                        String[] envPair=env.split(":");
                        insertImageEnv="INSERT INTO t_image_env(id,image,env_key,env_value,create_time,last_update_time) " +
                                "VALUES ('"+StringUtil.getUUID()+"','"+image+"','"+envPair[0]+"','"+envPair[1]+"',NOW(),NOW())";
                        insertSqls.add(insertImageEnv);
                    }
                }catch (Exception ex){
                    ex.printStackTrace();
                    return "参数设置失败,环境变量参数格式异常!";
                }
            }


        }
        //先执行批量删除功能
        String[] sqlDelete=new String[deleteSqls.size()];
        deleteSqls.toArray(sqlDelete);
        jdbcTemplateImpl.batchUpdate(sqlDelete);
        //再执行批量插入功能
        String[] sqlInsert=new String[insertSqls.size()];
        insertSqls.toArray(sqlInsert);
        jdbcTemplateImpl.batchUpdate(sqlInsert);
        return "参数设置成功!";
    }
}